﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Configuration;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using AdventureWorks.Cinema.BusinessLogic;
using AdventureWorks.Cinema.DataTransferObjects;
using AdventureWorks.Cinema.Server.WebService.Properties;

namespace AdventureWorks.Cinema.Server.WebService
{
    [WebService(Namespace = "http://AdventureWorks/Cinema/Server/WebService/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class WebService : System.Web.Services.WebService, ICinemaServiceContract
    {
     

        private SessionHeader sessionHeader;

        public SessionHeader SessionHeader
        {
            get { return sessionHeader; }
            set { sessionHeader = value; }
        }

        /// <summary>
        /// Wird von <see cref="LogException"/> verwendet, um eine
        /// SOAP-Ausnahme mit Details der Ausnahme zu erzeugen.
        /// Dieses Attribut sorgt dafür, dass Leerzeichen im XML Details
        /// Knoten erhalten bleiben (z.B. für den Stack Trace).
        /// </summary>
        /// <param name="doc">Das XML Dokument, für welches das Attribut
        /// erzeugt werden soll.
        /// </param>
        private XmlAttribute CreatePreserveWhitespaceAttribute(XmlDocument doc)
        {
            XmlAttribute result = doc.CreateAttribute("xml:space");
            result.Value = "preserve";
            return result;
        }

        /// <summary>
        /// Ausnahme-Protokollierung und Filterung für alle Web Service
        /// Methoden. Ausnahmen sollten nicht an den Client übertragen werden.
        /// </summary>
        /// <param name="ex">Die Ausnahme, die protokolliert werden soll.
        /// </param>
        private void LogException(Exception ex)
        {
            Trace.TraceError(ex.ToString());

            // "ForwardExceptions"-Einstellung aus web.config lesen
            bool forwardExceptions;
            string feSetting =
                WebConfigurationManager.AppSettings["ForwardExceptions"];
            bool.TryParse(feSetting, out forwardExceptions);

            XmlDocument doc = new XmlDocument();
            XmlNode detailsNode = doc.CreateNode(
                XmlNodeType.Element,
                SoapException.DetailElementName.Name,
                SoapException.DetailElementName.Namespace);

            // Keine CLR Ausnahmen an die Web Service Clients weiterleiten,
            // falls ForwardExceptions false ist (die Standardeinstellung).

            if (!(forwardExceptions || (ex is CinemaException)))
            {
                // Wir sollten keine möglicherweise vertraulichen
                // Informationen (Stack Trace, innere Ausnahmen usw.)
                // an den Client weiterleiten.

                XmlNode messageNode = doc.CreateElement("Message");

                if (ex is CinemaException)
                {
                    // Falls die Ausnahme von CinemaException abgeleitet
                    // ist, übertragen wir trotzdem den Fehlertext,
                    // da diese Ausnahmen dazu gedacht sind, an die
                    // Clients übertragen zu werden.

                    messageNode.InnerText = ex.Message;
                }
                else
                {
                    // Ansonsten übertragen wir nur eine einfache Nachricht
                    // die aussagt, dass ein interner Fehler aufgetreten ist.

                    messageNode.InnerText = Resources.InternalServerError;
                }

                detailsNode.AppendChild(messageNode);
            }
            else
            {
                Exception currentException;

                // Erzeuge eine Nachricht, die alle Ausnahmen
                // inklusive der inneren Ausnahmen enthält.

                StringBuilder messageBuilder = new StringBuilder();
                currentException = ex;
                while (currentException != null)
                {
                    if (messageBuilder.Length > 0)
                        messageBuilder.Append(Environment.NewLine);

                    messageBuilder.Append(currentException.Message);
                    currentException = currentException.InnerException;
                }

                XmlNode messageNode = doc.CreateElement("Message");
                messageNode.Attributes.Append(
                    CreatePreserveWhitespaceAttribute(doc));
                messageNode.InnerText = messageBuilder.ToString();
                detailsNode.AppendChild(messageNode);

                // Erzeuge einen Baum aller Ausnahmen inklusive
                // des Typs, Stack Trace und der Fehlermeldung.

                XmlNode currentParent = detailsNode;
                currentException = ex;
                while (currentException != null)
                {
                    // Für Ausnahmen erzeugen wir einen Exception-Tag.
                    XmlNode exceptionNode = doc.CreateElement("Exception");
                    currentParent.AppendChild(exceptionNode);

                    // Typ der Ausnahme einfügen
                    XmlNode exceptionTypeNode = doc.CreateElement("Type");
                    exceptionTypeNode.InnerText =
                        currentException.GetType().FullName;
                    exceptionNode.AppendChild(exceptionTypeNode);

                    // Fehlermeldung einfügen
                    XmlNode exceptionMessageNode = doc.CreateElement("Message");
                    exceptionMessageNode.Attributes.Append(
                        CreatePreserveWhitespaceAttribute(doc));
                    exceptionMessageNode.InnerText =
                        currentException.Message;
                    exceptionNode.AppendChild(exceptionMessageNode);

                    // Stack Trace einfügen
                    XmlNode exceptionStackTraceNode =
                        doc.CreateElement("StackTrace");
                    exceptionStackTraceNode.Attributes.Append(
                        CreatePreserveWhitespaceAttribute(doc));
                    exceptionStackTraceNode.InnerText =
                        currentException.StackTrace;
                    exceptionNode.AppendChild(exceptionStackTraceNode);

                    // Weiter mit der inneren Ausnahme
                    currentException = currentException.InnerException;

                    // Die innere Ausnahme wird innerhalb des Tags der
                    // aktuellen Ausnahme erzeugt.
                    currentParent = exceptionNode;
                }
            }

            throw new SoapException(ex.Message, SoapException.ServerFaultCode,
                Context.Request.Url.AbsoluteUri, detailsNode);
        }

        private void EnsureSessionIsValid()
        {
            // Kein Sitzungs-Header -> Fehler!
            if (SessionHeader == null)
            {
                throw new NoSessionHeaderException(
                    Resources.NoSessionHeaderExceptionMessage);
            }

            Session session =
                SessionManager.GetSession(SessionHeader.SessionId);

            // Keine Sitzung zu dieser Id in der Datenbank
            if (session == null)
            {
                throw new SessionNotFoundException(
                    Resources.SessionNotFoundExceptionMessage);
            }

            // Die IP-Adresse stimmt nicht mit der gespeicherten
            // IP-Adresse für diese Sitzung überein.
            if (session.IPAddress != Context.Request.UserHostAddress)
            {
                throw new WrongIPException(Resources.WrongIPExceptionMessage);
            }

            // Weise dem aktuellen Thread einen Cinema-Principal zu.
            // Der Principal wird von der Geschäftslogik für
            // rollenbasierte Sicherheitsbeschränkungen verwendet.

            Thread.CurrentPrincipal = new CinemaPrincipal(session);
        }

        #region ICinemaServiceContract Members

        #region Performance

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPerformancesResponse GetPerformances(
            GetPerformancesRequest GetPerformancesRequestMessage)
        {
            GetPerformancesResponse response = new GetPerformancesResponse();

            try
            {
                response.Performances = PerformanceManager.GetPerformances(
                    GetPerformancesRequestMessage.StartDate,
                    GetPerformancesRequestMessage.EndDate);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPerformanceResponse GetPerformance(
            GetPerformanceRequest GetPerformanceRequestMessage)
        {
            GetPerformanceResponse response = new GetPerformanceResponse();

            try
            {
                response.Performance = PerformanceManager.GetPerformance(
                    GetPerformanceRequestMessage.PerformanceId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPerformancesResponse GetPerformancesOfRoom(
            GetPerformancesOfRoomRequest GetPerformancesOfRoomRequestMessage)
        {
            GetPerformancesResponse response = new GetPerformancesResponse();

            try
            {
                response.Performances =
                    PerformanceManager.GetPerformancesOfRoom(
                    GetPerformancesOfRoomRequestMessage.RoomId,
                    GetPerformancesOfRoomRequestMessage.StartDate,
                    GetPerformancesOfRoomRequestMessage.EndDate);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPerformancesResponse GetPerformancesOfMovie(
            GetPerformancesOfMovieRequest GetPerformancesOfMovieRequestMessage)
        {
            GetPerformancesResponse response = new GetPerformancesResponse();

            try
            {
                response.Performances =
                    PerformanceManager.GetPerformancesOfMovie(
                    GetPerformancesOfMovieRequestMessage.MovieId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetFreeSeatsResponse GetFreeSeats(
            GetFreeSeatsRequest GetFreeSeatsRequestMessage)
        {
            GetFreeSeatsResponse response = new GetFreeSeatsResponse();

            try
            {
                response.FreeSeats = PerformanceManager.GetFreeSeatCount(
                    GetFreeSeatsRequestMessage.PerformanceId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreatePerformance(
            CreatePerformanceRequest CreatePerformanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                PerformanceManager.CreatePerformance(
                    CreatePerformanceRequestMessage.Performance);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdatePerformance(
            UpdatePerformanceRequest UpdatePerformanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                PerformanceManager.UpdatePerformance(
                    UpdatePerformanceRequestMessage.Performance);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeletePerformance(
            DeletePerformanceRequest DeletePerformanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                PerformanceManager.DeletePerformance(
                    DeletePerformanceRequestMessage.PerformanceId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region Ticket

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public BuyTicketsResponse BuyTickets(
            BuyTicketsRequest BuyTicketsRequestMessage)
        {
            EnsureSessionIsValid();

            BuyTicketsResponse response = new BuyTicketsResponse();

            try
            {
                Session session = SessionManager.GetSession(
                    SessionHeader.SessionId);

                response.TicketCode = TicketManager.BuyTickets(
                    session.User,
                    BuyTicketsRequestMessage.PerformanceId,
                    BuyTicketsRequestMessage.Quantity);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void SellTickets(SellTicketsRequest SellTicketsRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                Session session = SessionManager.GetSession(
                    SessionHeader.SessionId);

                TicketManager.SellTickets(
                    SellTicketsRequestMessage.PerformanceId,
                    SellTicketsRequestMessage.Quantity);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetTicketResponse GetTicket(
            GetTicketRequest GetTicketRequestMessage)
        {
            EnsureSessionIsValid();

            GetTicketResponse response = new GetTicketResponse();

            try
            {
                response.Ticket = TicketManager.GetTicket(
                    GetTicketRequestMessage.TicketId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
            public GetUndispatchedTicketsResponse GetUndispatchedTickets(
            GetUndispatchedTicketsRequest GetUndispatchedTicketsRequestMessage)
        {
            EnsureSessionIsValid();

            GetUndispatchedTicketsResponse response =
                new GetUndispatchedTicketsResponse();

            try
            {
                response.Tickets = TicketManager.GetUndispatchedTickets(
                    GetUndispatchedTicketsRequestMessage.TicketCode);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetUndispatchedTicketsResponse GetUndispatchedTicketsByUserId(
            GetUndispatchedTicketsByUserIdRequest
            GetUndispatchedTicketsByUserIdRequestMessage)
        {
            EnsureSessionIsValid();

            GetUndispatchedTicketsResponse response =
                new GetUndispatchedTicketsResponse();

            try
            {
                response.Tickets = TicketManager.GetUndispatchedTicketsByUserId(
                    GetUndispatchedTicketsByUserIdRequestMessage.UserId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void MarkTicketAsDispatched(
            MarkTicketAsDispatchedRequest MarkTicketAsDispatchedRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                TicketManager.MarkTicketAsDispatched(
                    MarkTicketAsDispatchedRequestMessage.TicketId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region Movie

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetMoviesResponse GetMovies()
        {
            GetMoviesResponse response = new GetMoviesResponse();

            try
            {
                response.MovieList = MovieManager.GetMovies();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetMovieResponse GetMovie(GetMovieRequest GetMovieRequestMessage)
        {
            GetMovieResponse response = new GetMovieResponse();

            try
            {
                response.Movie = MovieManager.GetMovie(
                    GetMovieRequestMessage.MovieId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetMoviesResponse GetMoviesByName(
            GetMoviesByNameRequest GetMoviesByNameRequestMessage)
        {
            GetMoviesResponse response = new GetMoviesResponse();

            try
            {
                response.MovieList = MovieManager.GetMoviesByName(
                    GetMoviesByNameRequestMessage.MovieName);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetMoviesResponse GetMoviesByUserInterests(
            GetMoviesByUserInterestsRequest
            GetMoviesByUserInterestsRequestMessage)
        {
            EnsureSessionIsValid();

            GetMoviesResponse response = new GetMoviesResponse();

            try
            {
                response.MovieList =
                    UserManager.GetMoviesByUserInterest(
                    GetMoviesByUserInterestsRequestMessage.UserId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateMovie(CreateMovieRequest CreateMovieRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                MovieManager.CreateMovie(CreateMovieRequestMessage.Movie);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateMovie(UpdateMovieRequest UpdateMovieRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                MovieManager.UpdateMovie(UpdateMovieRequestMessage.Movie);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteMovie(DeleteMovieRequest DeleteMovieRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                MovieManager.DeleteMovie(DeleteMovieRequestMessage.MovieId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void RateMovie(RateMovieRequest RateMovieRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                Session session = SessionManager.GetSession(
                    SessionHeader.SessionId);

                MovieManager.RateMovie(
                    session.User,
                    RateMovieRequestMessage.MovieId,
                    RateMovieRequestMessage.Rating);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region Room

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetRoomsResponse GetRooms()
        {
            GetRoomsResponse response = new GetRoomsResponse();

            try
            {
                response.RoomList = RoomManager.GetRooms();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateRoom(CreateRoomRequest CreateRoomRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                RoomManager.CreateRoom(CreateRoomRequestMessage.Room);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateRoom(UpdateRoomRequest UpdateRoomRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                RoomManager.UpdateRoom(UpdateRoomRequestMessage.Room);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteRoom(DeleteRoomRequest DeleteRoomRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                RoomManager.DeleteRoom(DeleteRoomRequestMessage.RoomId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region User

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetUserDataResponse GetUserData(
            GetUserDataRequest GetUserDataRequestMessage)
        {
            EnsureSessionIsValid();

            GetUserDataResponse response = new GetUserDataResponse();

            try
            {
                response.UserData = UserManager.GetUser(
                    GetUserDataRequestMessage.UserId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetUsersForNewsletterResponse GetUsersForNewsletter()
        {
            EnsureSessionIsValid();

            GetUsersForNewsletterResponse response =
                new GetUsersForNewsletterResponse();

            try
            {
                response.UserList =
                    UserManager.GetUsersForNewsletter();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        public void CreateUser(CreateUserRequest CreateUserRequestMessage)
        {
            try
            {
                UserManager.CreateUser(CreateUserRequestMessage.User,
                    CreateUserRequestMessage.Password);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateUser(UpdateUserRequest UpdateUserRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                UserManager.UpdateUser(
                    UpdateUserRequestMessage.User);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteUser(DeleteUserRequest DeleteUserRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                UserManager.DeleteUser(
                    DeleteUserRequestMessage.UserId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }


        #endregion

        #region NewsItem

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetNewsItemsResponse GetNewsItems()
        {
            GetNewsItemsResponse response = new GetNewsItemsResponse();

            try
            {
                response.NewsItemList = NewsManager.GetNews();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetNewsItemsResponse GetNewsItemsByCategoryNumber(
            GetNewsItemsByCategoryNumbersRequest
            GetNewsItemsByCategoryNumberRequestMessage)
        {
            GetNewsItemsResponse response = new GetNewsItemsResponse();

            try
            {
                response.NewsItemList =
                    NewsManager.GetNewsItemsByCategoryNumbers(
                    GetNewsItemsByCategoryNumberRequestMessage.CategoryNumbers);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateNewsItem(
            CreateNewsItemRequest CreateNewsItemRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsManager.CreateNewsItem(
                    CreateNewsItemRequestMessage.NewsItem);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateNewsItem(
            UpdateNewsItemRequest UpdateNewsItemRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsManager.UpdateNewsItem(
                    UpdateNewsItemRequestMessage.NewsItem);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteNewsItem(
            DeleteNewsItemRequest DeleteNewsItemRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsManager.DeleteNewsItem(
                    DeleteNewsItemRequestMessage.NewsItemId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region NewsCategory

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetNewsCategoriesResponse GetNewsCategories()
        {
            GetNewsCategoriesResponse response =
                new GetNewsCategoriesResponse();

            try
            {
                response.NewsCategories =
                    NewsCategoryManager.GetAllNewsCategories();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateNewsCategory(
            CreateNewsCategoryRequest CreateNewsCategoryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsCategoryManager.CreateNewsCategory(
                    CreateNewsCategoryRequestMessage.NewsCategory);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateNewsCategory(
            UpdateNewsCategoryRequest UpdateNewsCategoryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsCategoryManager.UpdateNewsCategory(
                    UpdateNewsCategoryRequestMessage.NewsCategory);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteNewsCategory(
            DeleteNewsCategoryRequest DeleteNewsCategoryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                NewsCategoryManager.DeleteNewsCategory(
                    DeleteNewsCategoryRequestMessage.NewsCategoryId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        #endregion

        #region LogOn / LogOff

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.Out)]
        public LogOnResponse LogOn(LogOnRequest LogOnRequestMessage)
        {
            LogOnResponse response = new LogOnResponse();

            try
            {
                response.User = UserManager.LogOn(
                    LogOnRequestMessage.UserName, LogOnRequestMessage.Password);

                Session session = new Session();
                session.User = response.User;
                session.Id = Guid.NewGuid();
                session.IPAddress = Context.Request.UserHostAddress;
                session.StartDate = DateTime.Now;

                SessionManager.CreateSession(session);

                SessionHeader = new SessionHeader();
                SessionHeader.SessionId = session.Id;

            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.InOut)]
        public void LogOff()
        {
            EnsureSessionIsValid();

            try
            {
                UserManager.LogOff();

                SessionManager.DeleteSession(SessionHeader.SessionId);
                SessionHeader.SessionId = Guid.Empty;
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void ChangePassword(
            ChangePasswordRequest ChangePasswordRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                Session session = SessionManager.GetSession(
                    SessionHeader.SessionId);
                UserManager.ChangePassword(
                    session.User,
                    ChangePasswordRequestMessage.CurrentPassword,
                    ChangePasswordRequestMessage.NewPassword);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        public void ResetPassword(
            ResetPasswordRequest ResetPasswordRequestMessage)
        {
            try
            {
                UserManager.ResetPassword(ResetPasswordRequestMessage.UserName);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetCurrentUserResponse GetCurrentUser()
        {
            EnsureSessionIsValid();

            GetCurrentUserResponse response = new GetCurrentUserResponse();

            try
            {
                response.CurrentUser = CinemaPrincipal.Current.Identity.User;
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        #endregion

        #region Genre

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateGenre(CreateGenreRequest CreateGenreRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                GenreManager.CreateGenre(CreateGenreRequestMessage.Genre);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateGenre(UpdateGenreRequest UpdateGenreRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                GenreManager.UpdateGenre(UpdateGenreRequestMessage.Genre);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteGenre(DeleteGenreRequest DeleteGenreRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                GenreManager.DeleteGenre(DeleteGenreRequestMessage.GenreId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetAllGenresResponse GetAllGenres()
        {
            GetAllGenresResponse response = new GetAllGenresResponse();

            try
            {
                response.Genres = GenreManager.GetAllGenres();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        #endregion

        #region Country

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateCountry(
            CreateCountryRequest CreateCountryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                CountryManager.CreateCountry(
                    CreateCountryRequestMessage.Country);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateCountry(
            UpdateCountryRequest UpdateCountryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                CountryManager.UpdateCountry(
                    UpdateCountryRequestMessage.Country);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteCountry(
            DeleteCountryRequest DeleteCountryRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                CountryManager.DeleteCountry(
                    DeleteCountryRequestMessage.CountryId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetAllCountriesResponse GetAllCountries()
        {
            GetAllCountriesResponse response = new GetAllCountriesResponse();

            try
            {
                response.Countries = CountryManager.GetAllCountries();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        #endregion

        #region Distributor

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateDistributor(
            CreateDistributorRequest CreateDistributorRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                DistributorManager.CreateDistributor(
                    CreateDistributorRequestMessage.Distributor);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateDistributor(
            UpdateDistributorRequest UpdateDistributorRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                DistributorManager.UpdateDistributor(
                    UpdateDistributorRequestMessage.Distributor);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteDistributor(
            DeleteDistributorRequest DeleteDistributorRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                DistributorManager.DeleteDistributor(
                    DeleteDistributorRequestMessage.DistributorId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetAllDistributorsResponse GetAllDistributors()
        {
            GetAllDistributorsResponse response =
                new GetAllDistributorsResponse();

            try
            {
                response.Distributors = DistributorManager.GetAllDistributors();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
            return response;
        }

        #endregion

        #region ParentalGuidance

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreateParentalGuidance(
            CreateParentalGuidanceRequest CreateParentalGuidanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                ParentalGuidanceManager.CreateParentalGuidance(
                    CreateParentalGuidanceRequestMessage.ParentalGuidance);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdateParentalGuidance(
            UpdateParentalGuidanceRequest UpdateParentalGuidanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                ParentalGuidanceManager.UpdateParentalGuidance(
                    UpdateParentalGuidanceRequestMessage.ParentalGuidance);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeleteParentalGuidance(
            DeleteParentalGuidanceRequest DeleteParentalGuidanceRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                ParentalGuidanceManager.DeleteParentalGuidance(
                    DeleteParentalGuidanceRequestMessage.ParentalGuidanceId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetAllParentalGuidancesResponse GetAllParentalGuidances()
        {
            GetAllParentalGuidancesResponse response =
                new GetAllParentalGuidancesResponse();

            try
            {
                response.ParentalGuidances =
                    ParentalGuidanceManager.GetAllParentalGuidances();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        #endregion

        #region Person

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void CreatePerson(CreatePersonRequest CreatePersonRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                PersonManager.CreatePerson(CreatePersonRequestMessage.Person);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void UpdatePerson(UpdatePersonRequest UpdatePersonRequestMessage)
        {
             EnsureSessionIsValid();

            try
            {
                PersonManager.UpdatePerson(UpdatePersonRequestMessage.Person);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public void DeletePerson(DeletePersonRequest DeletePersonRequestMessage)
        {
            EnsureSessionIsValid();

            try
            {
                PersonManager.DeletePerson(DeletePersonRequestMessage.PersonId);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPersonsResponse GetAllPersons()
        {
            EnsureSessionIsValid();

            GetPersonsResponse response = new GetPersonsResponse();

            try
            {
                response.Persons = PersonManager.GetAllPersons();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        [WebMethod]
        [SoapHeader("SessionHeader", Direction = SoapHeaderDirection.In)]
        public GetPersonsResponse GetPersonByName(
            GetPersonByNameRequest GetPersonByNameRequestMessage)
        {
            EnsureSessionIsValid();

            GetPersonsResponse response = new GetPersonsResponse();

            try
            {
                response.Persons = PersonManager.GetPersonByName(
                    GetPersonByNameRequestMessage.Name);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return response;
        }

        #endregion

        #endregion
    }
}
